﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Mbr.Reviews.Core.Contracts;

namespace Mbr.Reviews.Core.ProductProviders
{
    public class InMemoryProductProvider : IProvideProducts
    {
        private const int nameRelevanceFactor = 3;
        private const int tagRelevanceFactor = 2;
        private const int descriptionRelevanceFactor = 1;

        private readonly List<Contracts.DTO.Product> products = new List<Contracts.DTO.Product>(new Contracts.DTO.Product[] { 
            new Contracts.DTO.Product
            {
                Id = "1",
                Name = "Nokia Lumia 900",
                Uri = new Uri("http://www.google.com"),
                Description = "Nokia Lumia 900 Smartphone",
                Tags = new string[]{}
            },
            new Contracts.DTO.Product
            {
                Id = "2",
                Name = "Samsung Galaxy Tab",
                Uri = new Uri("http://www.google.com"),
                Description = "Samsung Galaxy Tab Tablet with Android",
                Tags = new string[]{}
            },
            new Contracts.DTO.Product
            {
                Id = "3",
                Name = "Samsung Galaxy S3",
                Uri = new Uri("http://www.google.com"),
                Description = "The Samsung Galaxy S3 Smartphone",
                Tags = new string[]{}
            }
        });

        public IEnumerable<Contracts.DTO.Product> Find(params string[] keywords)
        {
            var productsWithRelevance = new List<ProductWithRelevance>(products.Count);

            products.ForEach(product =>
            {

                int relevance = nameRelevanceFactor * keywords.Where(k => product.Name.ToLowerInvariant().Contains(k.ToLowerInvariant())).Count();
                relevance += tagRelevanceFactor * keywords.Where(k => product.Tags.Any(t => string.Equals(k, t, StringComparison.InvariantCultureIgnoreCase))).Count();
                relevance += descriptionRelevanceFactor * keywords.Where(k => product.Description.ToLowerInvariant().Contains(k.ToLowerInvariant())).Count();

                productsWithRelevance.Add(new ProductWithRelevance
                {
                    Product = product,
                    Relevance = relevance
                });

            });

            return productsWithRelevance
                .Where(p => p.Relevance > 0)
                .OrderByDescending(p => p.Relevance)
                .Select(p => p.Product)
                .ToArray();
        }

        private class ProductWithRelevance
        {
            public Contracts.DTO.Product Product { get; set; }
            public int Relevance { get; set; }
        }
    }
}
